package com.spark.common.widget

import android.animation.Animator
import android.animation.AnimatorListenerAdapter
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Bitmap
import android.graphics.Canvas
import android.graphics.PixelFormat
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.graphics.drawable.NinePatchDrawable
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.view.animation.AccelerateDecelerateInterpolator
import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.widget.FrameLayout
import android.widget.TextView
import com.spark.common.R

class DiscView(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : FrameLayout(context, attrs, defStyleAttr) {

    private var mContext: Context? = null
    private lateinit var mCircleView: CircleView
    private var animator: ValueAnimator? = null
    private var headText: TextView? = null//头部Text
    private var contentValueText: TextView? = null//属性Text
    private var bottomText: TextView? = null//底部Text

    private var afterAnimation: Animation? = null//设值完毕后动画

    constructor(context: Context) : this(context, null, 0)
    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)


    companion object {
        val ANIMATION_DURING = 1100
    }

    init {
        initView(context, null)
    }

    private fun initView(context: Context, attrs: AttributeSet?) {
        this.mContext = context
        animator = ValueAnimator.ofInt(0, 0)//属性动画差值器

        val inflater = LayoutInflater.from(context)
        val v = inflater.inflate(R.layout.view_disc_layout, this, true)
        mCircleView = v.findViewById<View>(R.id.circle_view) as CircleView
        headText = v.findViewById<View>(R.id.head_title) as TextView
        contentValueText = v.findViewById<View>(R.id.value_content) as TextView
        bottomText = v.findViewById<View>(R.id.bottom_title) as TextView

        readAttributeAndSet(context, attrs)

        afterAnimation = AnimationUtils.loadAnimation(mContext, R.anim.scale_animation)
    }

    //配置属性读取并配置
    private fun readAttributeAndSet(context: Context, attrs: AttributeSet?) {
        val a = context.obtainStyledAttributes(attrs, R.styleable.DiscView)
        mCircleView.stokenWidth = a.getDimensionPixelSize(R.styleable.DiscView_dvStrokenWidth,
                mCircleView.stokenWidth)//宽度属性读取
        mCircleView.mCircleMode = a.getInt(R.styleable.DiscView_dvCircleMode, mCircleView.mCircleMode)//读取圆环模式

        //读取外装饰圆圈是否显示
        mCircleView.mOuterCircleIsShow = a.getBoolean(R.styleable.DiscView_dvOuterCircleShow, mCircleView.mOuterCircleIsShow)
        mCircleView.mOuterCirclePad = a.getDimensionPixelSize(R.styleable.DiscView_dvOuterCirclePad, mCircleView.mOuterCirclePad)//外圆边距

        //读取圆圈颜色设置
        mCircleView.mRadiusColor = a.getColor(R.styleable.DiscView_dvStrokenColor, mCircleView.mRadiusColor)

        //读取外装饰圆圈是否显示
        mCircleView.mInnerCircleIsShow = a.getBoolean(R.styleable.DiscView_dvInnerCircleShow, mCircleView.mInnerCircleIsShow)
        mCircleView.mInnerCirclePad = a.getDimensionPixelSize(R.styleable.DiscView_dvInnerCirclePad, mCircleView.mInnerCirclePad)//外圆边距
        mCircleView.issBottomCircleShow = a.getBoolean(R.styleable.DiscView_dvBottomCircleIsShow, false)
        val bitDrawable = a.getDrawable(R.styleable.DiscView_dvIndicatorDraw)
        var indicatorBit: Bitmap? = null
        if (bitDrawable != null) {
            indicatorBit = bitDrawable.toBitmap()
        }

        //读取开始角度偏移量
        mCircleView.startRotateAngle = a.getInteger(R.styleable.DiscView_dvStartRotateAngle, CircleView.MIN_VALUE)
        //读取圆盘可旋转范围
        mCircleView.angleRotateSpan = a.getInteger(R.styleable.DiscView_dvAngleRotateSpan, CircleView.MAX_VALUE)
        a.recycle()

        mCircleView.setStrokenWidth(mCircleView.stokenWidth)
        mCircleView.setCircleMode(mCircleView.mCircleMode)
        mCircleView.setOuterCircle(mCircleView.mOuterCircleIsShow, mCircleView.mOuterCirclePad)
        mCircleView.setRadiusColor(mCircleView.mRadiusColor)
        mCircleView.setInnerCircle(mCircleView.mInnerCircleIsShow, mCircleView.mInnerCirclePad)
        mCircleView.setBottomCircleShow(mCircleView.issBottomCircleShow)
        mCircleView.setIndicatorBit(indicatorBit
                ?: Bitmap.createBitmap(10, 10, Bitmap.Config.ARGB_8888))

        mCircleView.startRotateAngle = mCircleView.startRotateAngle
        mCircleView.angleRotateSpan = mCircleView.angleRotateSpan
    }

    /**
     * 设置指示器的值 min - max之间
     *
     * @param value
     */
    @SuppressLint("SetTextI18n")
    @JvmOverloads
    fun setValue(value: Int, duration: Int = ANIMATION_DURING) {
        if (animator!!.isRunning) {//上次动画未结束
            animator!!.cancel()//取消上次动画
            mCircleView.clearAnimation()
        }

        animator = ValueAnimator.ofInt(0, value)?.apply {
            interpolator = AccelerateDecelerateInterpolator()//先加速 后减速差值
            this.duration = duration.toLong()
            start()
            addUpdateListener { animation ->
                val value = animation.animatedValue as Int
                mCircleView.setValue(value)
                contentValueText!!.text = "" + value
            }

            addListener(object : AnimatorListenerAdapter() {
                override fun onAnimationEnd(animation: Animator) {
                    mCircleView.startAnimation(afterAnimation)
                }

                override fun onAnimationCancel(animation: Animator) {}
            })
        }
    }
}//end class

fun Drawable.toBitmap(): Bitmap? {
    when {
        this is BitmapDrawable -> return bitmap
        this is NinePatchDrawable -> {
            val btp = Bitmap
                    .createBitmap(
                            intrinsicWidth,
                            intrinsicHeight,
                            if (opacity != PixelFormat.OPAQUE) Bitmap.Config.ARGB_8888 else Bitmap.Config.RGB_565
                    )
            val canvas = Canvas(btp)
            setBounds(0, 0, intrinsicWidth, intrinsicHeight)
            draw(canvas)
            return btp
        }
        else -> return null
    }
}